<!DOCTYPE html>
<html lang="zh-CN">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>拖拽缩放旋转图片编辑器</title>
    <style>
        * {
            margin: 0;
            padding: 0;
            box-sizing: border-box;
            user-select: none;
        }

        body {
            font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
            background: linear-gradient(135deg, #1a2a6c, #b21f1f, #fdbb2d);
            min-height: 100vh;
            display: flex;
            flex-direction: column;
            align-items: center;
            padding: 30px;
            color: #fff;
        }

        .header {
            text-align: center;
            margin-bottom: 30px;
        }

        .header h1 {
            font-size: 2.8rem;
            margin-bottom: 10px;
            text-shadow: 0 3px 6px rgba(0, 0, 0, 0.3);
        }

        .header p {
            font-size: 1.2rem;
            opacity: 0.9;
            max-width: 600px;
            line-height: 1.6;
        }

        .container {
            display: flex;
            flex-wrap: wrap;
            gap: 40px;
            justify-content: center;
            width: 100%;
            max-width: 1200px;
        }

        .editor-container {
            position: relative;
            width: 800px;
            height: 500px;
            border-radius: 12px;
            overflow: hidden;
            box-shadow: 0 12px 30px rgba(0, 0, 0, 0.4);
            background: rgba(20, 20, 30, 0.7);
        }

        #baseImage {
            width: 100%;
            height: 100%;
            object-fit: cover;
        }

        .area-frame {
            position: absolute;
            top: 30%;
            left: 30%;
            width: 40%;
            height: 40%;
            border: 4px dashed rgba(255, 255, 255, 0.7);
            box-shadow: 0 0 15px rgba(255, 215, 0, 0.7);
            pointer-events: none;
            z-index: 10;
            transition: all 0.3s ease;
        }

        .area-label {
            position: absolute;
            bottom: -40px;
            left: 0;
            width: 100%;
            text-align: center;
            font-weight: 600;
            color: gold;
            text-shadow: 0 1px 2px rgba(0, 0, 0, 0.8);
        }

        .control-point {
            position: absolute;
            width: 20px;
            height: 20px;
            background: rgba(255, 255, 255, 0.8);
            border: 2px solid #ffd700;
            border-radius: 50%;
            z-index: 20;
            transition: all 0.3s ease;
            pointer-events: auto;
        }

        .control-point:hover {
            transform: scale(1.2);
            background: #ffd700;
        }

        .control-point.top-left {
            top: -10px;
            left: -10px;
            cursor: nw-resize;
        }

        .control-point.top-right {
            top: -10px;
            right: -10px;
            cursor: ne-resize;
        }

        .control-point.bottom-left {
            bottom: -10px;
            left: -10px;
            cursor: sw-resize;
        }

        .control-point.bottom-right {
            bottom: -10px;
            right: -10px;
            cursor: se-resize;
        }

        #uploadedImageContainer {
            position: absolute;
            top: 30%;
            left: 30%;
            width: 40%;
            height: 40%;
            overflow: hidden; 
            z-index: 5;
        }

        #resizableImageWrapper {
            position: absolute;
            top: 20%;
            left: 24%;
            width: 45%;
            height: 45%;
            z-index: 5;
            padding: 20px;
            border: 1px solid #2196F3;
            transform-origin: center center;
            cursor: grab;
            pointer-events: auto;
        }

        #uploadedImage {
            position: absolute;
            width: 100%;
            height: 100%;
            object-fit: contain;
            pointer-events: none;
            transform-origin: center center;
        }

        .controls {
            display: flex;
            flex-direction: column;
            align-items: center;
            justify-content: center;
            gap: 25px;
            background: rgba(10, 15, 30, 0.8);
            padding: 30px;
            border-radius: 15px;
            width: 300px;
            box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);
        }

        .control-group {
            width: 100%;
            text-align: center;
        }

        .control-group h3 {
            margin-bottom: 15px;
            color: #ffd700;
            font-size: 1.4rem;
        }

        .buttons {
            display: flex;
            flex-wrap: wrap;
            gap: 15px;
            justify-content: center;
        }

        .btn {
            background: linear-gradient(to right, #4a00e0, #8e2de2);
            color: white;
            border: none;
            padding: 14px 28px;
            font-size: 1.1rem;
            font-weight: 600;
            border-radius: 50px;
            cursor: pointer;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
            transition: all 0.3s ease;
            text-transform: uppercase;
            letter-spacing: 1px;
        }

        .btn:hover {
            transform: translateY(-3px);
            box-shadow: 0 8px 20px rgba(0, 0, 0, 0.5);
        }

        .btn:active {
            transform: translateY(1px);
        }

        #fileInput {
            display: none;
        }

        .slider-container {
            width: 100%;
            margin-top: 15px;
        }

        .slider {
            width: 100%;
            height: 8px;
            background: rgba(255, 255, 255, 0.2);
            border-radius: 4px;
            outline: none;
            -webkit-appearance: none;
        }

        .slider::-webkit-slider-thumb {
            -webkit-appearance: none;
            width: 22px;
            height: 22px;
            border-radius: 50%;
            background: #ffd700;
            cursor: pointer;
            box-shadow: 0 2px 8px rgba(0, 0, 0, 0.4);
        }

        .instructions {
            background: rgba(10, 15, 30, 0.8);
            padding: 25px;
            border-radius: 15px;
            margin-top: 30px;
            max-width: 800px;
            box-shadow: 0 8px 25px rgba(0, 0, 0, 0.3);
        }

        .instructions h2 {
            color: #ffd700;
            text-align: center;
            margin-bottom: 20px;
        }

        .instructions ul {
            padding-left: 30px;
            list-style-type: none;
        }

        .instructions li {
            margin-bottom: 15px;
            padding-left: 30px;
            position: relative;
            line-height: 1.6;
        }

        .instructions li:before {
            content: "•";
            position: absolute;
            left: 0;
            color: #ffd700;
            font-size: 24px;
        }

        .cursor-info {
            display: flex;
            align-items: center;
            gap: 10px;
            padding: 10px;
            background: rgba(255, 255, 255, 0.1);
            border-radius: 8px;
            margin-top: 10px;
        }

        .cursor-info div {
            display: flex;
            align-items: center;
            gap: 5px;
            font-size: 0.9rem;
        }

        .cursor-sample {
            width: 20px;
            height: 20px;
            border-radius: 50%;
        }

        .move {
            background: #4CAF50;
        }

        .rotate {
            background: #FF5722;
        }

        .zoom {
            background: #2196F3;
        }

        .download-overlay {
            position: fixed;
            top: 0;
            left: 0;
            width: 100%;
            height: 100%;
            background: rgba(0, 0, 0, 0.9);
            display: flex;
            justify-content: center;
            align-items: center;
            z-index: 1000;
            opacity: 0;
            pointer-events: none;
            transition: all 0.5s ease;
        }

        .download-container {
            background: rgba(30, 30, 50, 0.95);
            border-radius: 15px;
            padding: 30px;
            max-width: 500px;
            width: 90%;
            text-align: center;
            transform: scale(0.8);
            transition: all 0.5s ease;
        }

        .download-container h2 {
            color: #ffd700;
            margin-bottom: 20px;
        }

        #resultImage {
            max-width: 100%;
            border: 2px solid #ffd700;
            border-radius: 8px;
            margin-bottom: 25px;
        }

        .download-btn {
            background: linear-gradient(to right, #00b09b, #96c93d);
            color: white;
            border: none;
            padding: 14px 35px;
            font-size: 1.1rem;
            font-weight: bold;
            border-radius: 50px;
            cursor: pointer;
            transition: all 0.3s ease;
            box-shadow: 0 5px 15px rgba(0, 0, 0, 0.3);
        }

        .download-btn:hover {
            transform: translateY(-3px);
            box-shadow: 0 8px 20px rgba(0, 0, 0, 0.5);
        }

        .close-btn {
            position: absolute;
            top: 15px;
            right: 15px;
            color: white;
            font-size: 24px;
            cursor: pointer;
            transition: all 0.3s ease;
        }

        .close-btn:hover {
            color: #ffd700;
            transform: scale(1.1);
        }

        @media (max-width: 900px) {
            .container {
                flex-direction: column;
                align-items: center;
            }
            
            .editor-container {
                width: 100%;
                height: 400px;
            }
            
            .controls {
                width: 100%;
                max-width: 800px;
            }
        }
    </style>
</head>
<body>
    <div class="header">
        <h1>拖拽缩放旋转图片编辑器</h1>
        <p>上传图片后可在指定区域内移动、缩放和旋转图像，然后保存合成后的结果</p>
    </div>

    <div class="container">
        <div class="editor-container">
            <img id="baseImage" src="./txzm.jpg" alt="Background">
            
            <div class="area-frame">
                <div class="area-label">操作区域</div>
            </div>
            <div id="resizableImageWrapper" style="padding: 20px; transform: translate(26px, 41px) scale(1) rotate(0deg); cursor: grab;">
                <div class="control-point top-left"></div>
                <div class="control-point top-right"></div>
                <div class="control-point bottom-left"></div>
                <div class="control-point bottom-right"></div>
            </div>
            <div id="uploadedImageContainer">
                <!-- 用户上传的图片和操作框将在这里显示 -->
            </div>
        </div>
        
        <div class="controls">
            <div class="control-group">
                <h3>上传控制</h3>
                <div class="buttons">
                    <button id="uploadBtn" class="btn">上传图片</button>
                    <input type="file" id="fileInput" accept="image/*">
                </div>
            </div>
            
            <div class="control-group">
                <h3>操作控制</h3>
                <div class="buttons">
                    <button id="resetBtn" class="btn">重置</button>
                    <button id="saveBtn" class="btn">保存结果</button>
                </div>
            </div>
            
            <div class="control-group">
                <h3>缩放控制</h3>
                <input type="range" id="scaleSlider" class="slider" min="0.1" max="2" step="0.05" value="1">
                
                <div class="buttons" style="margin-top: 20px;">
                    <button id="zoomInBtn" class="btn">放大</button>
                    <button id="zoomOutBtn" class="btn">缩小</button>
                </div>
            </div>
            
            <div class="control-group">
                <h3>旋转控制</h3>
                <div class="buttons">
                    <button id="rotateLeftBtn" class="btn">左旋转</button>
                    <button id="rotateRightBtn" class="btn">右旋转</button>
                </div>
            </div>
            
            <div class="cursor-info">
                <div><span class="cursor-sample move"></span>拖拽移动</div>
                <div><span class="cursor-sample rotate"></span>旋转</div>
                <div><span class="cursor-sample zoom"></span>缩放</div>
            </div>
        </div>
    </div>
    
    <div class="instructions">
        <h2>使用说明</h2>
        <ul>
            <li>点击"上传图片"按钮选择要操作的图像文件</li>
            <li>上传后的图片会显示在操作区域（虚线框）内</li>
            <li>拖动图片可移动位置（光标为<span style="color:#4CAF50">绿色</span>）</li>
            <li>使用"放大"/"缩小"按钮或滑动条调整图片大小（光标为<span style="color:#2196F3">蓝色</span>）</li>
            <li>使用"左旋转"/"右旋转"按钮旋转图片（光标为<span style="color:#FF5722">橙色</span>）</li>
            <li>点击"保存结果"将处理后的图片和背景合成为最终图像</li>
        </ul>
    </div>
    
    <div class="download-overlay" id="downloadOverlay">
        <div class="download-container">
            <span class="close-btn">&times;</span>
            <h2>处理结果</h2>
            <img id="resultImage" alt="Result">
            <a id="downloadLink"><button class="download-btn">下载图片</button></a>
        </div>
    </div>

    <script>
        // 1. 全局变量声明
        let uploadedImage = null;
        let isDragging = false;
        let startPos = { x: 0, y: 0 }; // Mouse start position
        let currentPos = { x: 0, y: 0 }; // Current transform translate X, Y for imageManipulator
        let initialTranslateX = 0; // imageManipulator's translate X at drag start (from our internal state)
        let initialTranslateY = 0; // imageManipulator's translate Y at drag start (from our internal state)
        let currentRotation = 0;
        let currentScale = 1;

        let isControlPointDragging = false;
        let activeControlPoint = null;
        let startAngle = 0;
        let startDistance = 0;

        let imageManipulator = null; // This will hold the dynamically created resizableImageWrapper

        // DOM元素引用
        const baseImage = document.getElementById('baseImage');
        const fileInput = document.getElementById('fileInput');
        const uploadBtn = document.getElementById('uploadBtn');
        const saveBtn = document.getElementById('saveBtn');
        const resetBtn = document.getElementById('resetBtn');
        const scaleSlider = document.getElementById('scaleSlider');
        const zoomInBtn = document.getElementById('zoomInBtn');
        const zoomOutBtn = document.getElementById('zoomOutBtn');
        const rotateLeftBtn = document.getElementById('rotateLeftBtn');
        const rotateRightBtn = document.getElementById('rotateRightBtn');
        const downloadOverlay = document.getElementById('downloadOverlay');
        const resultImage = document.getElementById('resultImage');
        const downloadLink = document.getElementById('downloadLink');
        const closeBtn = document.querySelector('.close-btn');
        const editorContainer = document.querySelector('.editor-container');

        // 2. 核心操作函数定义 (确保在 handleFileUpload 之前)

        // 应用所有变换（位置、缩放、旋转）到 imageManipulator 和 uploadedImage
        function applyTransform() {
            if (!imageManipulator || !uploadedImage) return;
            
            const transform = `translate(${currentPos.x}px, ${currentPos.y}px) scale(${currentScale}) rotate(${currentRotation}deg)`;
            imageManipulator.style.transform = transform;
            
            // 更新图片位置和transform
            updateImagePosition();
        }

        // 开始拖拽
        function startDrag(e) {
            // 只允许从wrapper开始拖拽
            if (e.target !== imageManipulator && !e.target.classList.contains('control-point')) return;
            
            isDragging = true;
            startPos = { x: e.clientX, y: e.clientY };
            
            // 获取当前transform值
            const style = window.getComputedStyle(imageManipulator);
            const matrix = new DOMMatrix(style.transform);
            
            // 更新初始位置
            initialTranslateX = matrix.m41;
            initialTranslateY = matrix.m42;
            
            imageManipulator.style.cursor = 'grabbing';
            
            e.preventDefault();
        }
        
        // 拖拽中
        function drag(e) {
            if (!isDragging) return;
            
            // 计算新的位置
            currentPos.x = initialTranslateX + (e.clientX - startPos.x);
            currentPos.y = initialTranslateY + (e.clientY - startPos.y);
            
            // 更新wrapper位置
            const transform = `translate(${currentPos.x}px, ${currentPos.y}px) scale(${currentScale}) rotate(${currentRotation}deg)`;
            imageManipulator.style.transform = transform;
            
            // 更新图片位置
            updateImagePosition();
            
            e.preventDefault();
        }
        
        // 停止拖拽
        function stopDrag() {
            isDragging = false;
            isControlPointDragging = false;
            activeControlPoint = null;
            
            if (imageManipulator) {
                imageManipulator.style.cursor = 'grab';
            }
        }
        
        // 控制点拖拽相关函数
        function startControlPointDrag(e) {
            if (!uploadedImage || !imageManipulator) return;
            
            isControlPointDragging = true;
            activeControlPoint = e.target;
            
            const rect = imageManipulator.getBoundingClientRect(); 
            const centerX = rect.left + rect.width / 2;
            const centerY = rect.top + rect.height / 2;
            
            startAngle = Math.atan2(e.clientY - centerY, e.clientX - centerX);
            startDistance = Math.sqrt(
                Math.pow(e.clientX - centerX, 2) + 
                Math.pow(e.clientY - centerY, 2)
            );
            
            e.preventDefault();
            e.stopPropagation(); // Prevent drag of the image when control point is dragged
        }

        // 3. 其他辅助函数定义

        // 更新缩放 - (现在不直接使用，但函数保留以防需要)
        function updateScale() {
            if (!imageManipulator) return;
            currentScale = parseFloat(scaleSlider.value);
            applyTransform();
        }
        
        // 调整缩放 - (现在不直接使用，但函数保留以防需要)
        function adjustScale(amount) {
            if (!imageManipulator) return;
            currentScale = Math.max(0.1, Math.min(2, currentScale + amount));
            // scaleSlider.value = currentScale;
            applyTransform();
        }
        
        // 旋转图片 - (现在不直接使用，但函数保留以防需要)
        function rotateImage(angle) {
            if (!imageManipulator) return;
            currentRotation += angle;
            applyTransform();
        }
        
        // 重置图像
        function resetImage() {
            if (!imageManipulator) return;
            
            // Recalculate initial position for centering within editorContainer
            const initialWidth = editorContainer.clientWidth * 0.4;
            const initialHeight = editorContainer.clientHeight * 0.4;

            currentPos.x = (editorContainer.clientWidth - initialWidth) / 2;
            currentPos.y = (editorContainer.clientHeight - initialHeight) / 2;

            currentScale = 1;
            currentRotation = 0;
            // scaleSlider.value = currentScale;

            imageManipulator.style.width = initialWidth + 'px';
            imageManipulator.style.height = initialHeight + 'px';

            applyTransform();
        }
        
        // 显示下载预览
        function showDownloadOverlay() {
            downloadOverlay.style.opacity = '1';
            downloadOverlay.style.pointerEvents = 'all';
            document.querySelector('.download-container').style.transform = 'scale(1)';
        }
        
        // 隐藏下载预览
        function hideDownloadOverlay() {
            downloadOverlay.style.opacity = '0';
            downloadOverlay.style.pointerEvents = 'none';
            document.querySelector('.download-container').style.transform = 'scale(0.8)';
        }

        // 4. 主要事件处理函数

        // 处理文件上传
        function handleFileUpload(e) {
            const file = e.target.files[0];
            if (!file || !file.type.match('image.*')) return;
            
            const reader = new FileReader();
            
            reader.onload = function(event) {
                // Clear previous content
                if (uploadedImage && uploadedImage.parentElement) {
                    uploadedImage.parentElement.removeChild(uploadedImage);
                }
                
                // Get the existing wrapper
                imageManipulator = document.getElementById('resizableImageWrapper');
                
                // Add drag listener for the wrapper itself (for movement)
                imageManipulator.addEventListener('mousedown', startDrag);

                // Add control point event listeners dynamically
                const controlPoints = imageManipulator.querySelectorAll('.control-point');
                controlPoints.forEach(point => {
                    point.addEventListener('mousedown', startControlPointDrag);
                });

                uploadedImage = new Image();
                uploadedImage.id = 'uploadedImage';
                uploadedImage.onload = function() {
                    // Add the image to the uploadedImageContainer
                    const uploadedImageContainer = document.getElementById('uploadedImageContainer');
                    uploadedImageContainer.appendChild(uploadedImage);
                    
                    // Reset transform values
                    currentPos.x = 0;
                    currentPos.y = 0;
                    currentScale = 1;
                    currentRotation = 0;
                    
                    // 同步resizableImageWrapper和uploadedImage的位置
                    const wrapperRect = imageManipulator.getBoundingClientRect();
                    const containerRect = uploadedImageContainer.getBoundingClientRect();
                    
                    // 计算相对位置
                    currentPos.x = wrapperRect.left - containerRect.left;
                    currentPos.y = wrapperRect.top - containerRect.top;
                    
                    // 设置初始位置
                    updateImagePosition();
                    
                    applyTransform(); // Apply initial transform
                };
                
                uploadedImage.src = event.target.result;
            };
            
            reader.readAsDataURL(file);
            
            fileInput.value = ''; // Reset file input
        }

        // 更新图片位置
        function updateImagePosition() {
            if (!imageManipulator || !uploadedImage) return;
            
            const wrapperRect = imageManipulator.getBoundingClientRect();
            const containerRect = uploadedImage.parentElement.getBoundingClientRect();
            
            // 计算相对位置
            const x = wrapperRect.left - containerRect.left;
            const y = wrapperRect.top - containerRect.top;
            
            // 设置图片位置和尺寸
            uploadedImage.style.left = x + 'px';
            uploadedImage.style.top = y + 'px';
            uploadedImage.style.width = wrapperRect.width + 'px';
            uploadedImage.style.height = wrapperRect.height + 'px';
            
            // 同步transform
            const style = window.getComputedStyle(imageManipulator);
            uploadedImage.style.transform = style.transform;
        }

        // 保存最终结果
        function saveResult() {
            if (!uploadedImage || !imageManipulator) {
                alert('请先上传图片！');
                return;
            }
            
            const baseImg = new Image();
            baseImg.crossOrigin = 'Anonymous';
            baseImg.src = baseImage.src;
            
            baseImg.onload = function() {
                // 创建Canvas
                const canvas = document.createElement('canvas');
                const ctx = canvas.getContext('2d');
                
                // 获取框架尺寸和位置 (area-frame is still used for cropping background)
                const frame = document.querySelector('.area-frame');
                const frameRect = frame.getBoundingClientRect();
                const editorContainerRect = editorContainer.getBoundingClientRect(); // Use global editorContainer
                
                // 计算框架在背景图上的位置和尺寸
                const baseImageNaturalWidth = baseImage.naturalWidth;
                const baseImageNaturalHeight = baseImage.naturalHeight;
                const baseImageDisplayedWidth = baseImage.clientWidth;
                const baseImageDisplayedHeight = baseImage.clientHeight;

                // Calculate scale from displayed base image to its natural size
                const scaleX = baseImageNaturalWidth / baseImageDisplayedWidth;
                const scaleY = baseImageNaturalHeight / baseImageDisplayedHeight;

                // Get relative position of the base image within its container for accurate scaling
                const baseImageRect = baseImage.getBoundingClientRect();
                const baseImageContainerRect = editorContainer.getBoundingClientRect(); // editorContainer is the parent

                const baseImageOffsetX = baseImageRect.left - baseImageContainerRect.left;
                const baseImageOffsetY = baseImageRect.top - baseImageContainerRect.top;

                const frameX_relativeToBaseImage = (frameRect.left - baseImageRect.left) * scaleX;
                const frameY_relativeToBaseImage = (frameRect.top - baseImageRect.top) * scaleY;

                const frameWidth_scaled = frameRect.width * scaleX;
                const frameHeight_scaled = frameRect.height * scaleY;


                // Set Canvas尺寸 to the scaled frame dimensions
                canvas.width = frameWidth_scaled;
                canvas.height = frameHeight_scaled;
                
                // 绘制背景图的框架区域
                ctx.drawImage(
                    baseImg,
                    frameX_relativeToBaseImage, frameY_relativeToBaseImage, frameWidth_scaled, frameHeight_scaled, // 背景图源裁剪区域
                    0, 0, canvas.width, canvas.height // Canvas绘制区域
                );
                
                // 绘制用户上传的图片（应用了所有变换）
                ctx.save();
                
                // Get transformation properties from imageManipulator
                const manipulatorRect = imageManipulator.getBoundingClientRect();
                
                // Calculate the position of the uploaded image (manipulator) relative to the editorContainer
                const manipulatorX_relativeToEditor = manipulatorRect.left - editorContainerRect.left;
                const manipulatorY_relativeToEditor = manipulatorRect.top - editorContainerRect.top;

                // Now, convert to relative to the base image (which is scaled to its natural size on canvas)
                // and then relative to the frame's position on the canvas
                const manipulatorX_scaledToBaseImage = (manipulatorX_relativeToEditor - baseImageOffsetX) * scaleX;
                const manipulatorY_scaledToBaseImage = (manipulatorY_relativeToEditor - baseImageOffsetY) * scaleY;

                // Position relative to the frame on the canvas
                const finalX = manipulatorX_scaledToBaseImage - frameX_relativeToBaseImage;
                const finalY = manipulatorY_scaledToBaseImage - frameY_relativeToBaseImage;

                // Calculate the final rendered size of the uploaded image on the canvas
                // The imageManipulator's current clientWidth/Height reflects its scaled size
                const finalRenderWidth = manipulatorRect.width * (uploadedImage.naturalWidth / uploadedImage.width);
                const finalRenderHeight = manipulatorRect.height * (uploadedImage.naturalHeight / uploadedImage.height);

                // Translate to the center of the image on the canvas (relative to canvas origin)
                ctx.translate(finalX + finalRenderWidth / 2, finalY + finalRenderHeight / 2);
                
                // Apply rotation
                ctx.rotate(currentRotation * Math.PI / 180);
                
                // Draw the image
                ctx.drawImage(
                    uploadedImage,
                    -finalRenderWidth / 2, // Draw from center, so offset by half width
                    -finalRenderHeight / 2, // Draw from center, so offset by half height
                    finalRenderWidth,
                    finalRenderHeight
                );
                
                ctx.restore();
                
                // 获取DataURL并显示结果
                const dataUrl = canvas.toDataURL('image/png');
                resultImage.src = dataUrl;
                downloadLink.href = dataUrl;
                downloadLink.download = 'composite-image.png';
                
                // 显示下载预览
                showDownloadOverlay();
            };
        }
        
        // 5. 初始化函数

        // 设置所有事件监听
        function setupEventListeners() {
            // Upload functionality
            uploadBtn.addEventListener('click', () => fileInput.click());
            fileInput.addEventListener('change', handleFileUpload);
            
            // Global listeners for drag and control point operations (mousemove, mouseup)
            window.addEventListener('mousemove', drag);
            window.addEventListener('mouseup', stopDrag);
            
            // Remove old/unused listeners if they somehow persist from previous iterations (safety)
            const oldControlPoints = document.querySelectorAll('.area-frame .control-point');
            oldControlPoints.forEach(point => {
                point.removeEventListener('mousedown', startControlPointDrag);
            });

            // Ensure manual scale/rotate buttons are not actively listened to if control points are main method
            scaleSlider.removeEventListener('input', updateScale);
            zoomInBtn.removeEventListener('click', () => adjustScale(0.1));
            zoomOutBtn.removeEventListener('click', () => adjustScale(-0.1));
            rotateLeftBtn.removeEventListener('click', () => rotateImage(-15));
            rotateRightBtn.removeEventListener('click', () => rotateImage(15));
            
            // Reset and Save
            resetBtn.addEventListener('click', resetImage);
            saveBtn.addEventListener('click', saveResult);
            
            // Download overlay controls
            closeBtn.addEventListener('click', hideDownloadOverlay);
            downloadOverlay.addEventListener('click', (e) => {
                if (e.target === downloadOverlay) hideDownloadOverlay();
            });
        }
        
        // 初始化编辑器
        function initializeEditor() {
            setupEventListeners();
        }
        
        // 6. 页面加载完成后初始化编辑器
        document.addEventListener('DOMContentLoaded', initializeEditor);
    </script>
</body>
</html> 